home *** CD-ROM | disk | FTP | other *** search
/ Amiga Collections: Topik / Topik - Disk 24 - Productivity (19xx)(Topik Public Domain)(PD)[WB].zip / Topik - Disk 24 - Productivity (19xx)(Topik Public Domain)(PD)[WB].adf / SpreadSheet / sc.c < prev    next >
C/C++ Source or Header  |  1990-01-31  |  17KB  |  815 lines

  1. /*    SC    A Spreadsheet Calculator
  2.  *        Main driver
  3.  *
  4.  *        original by James Gosling, September 1982
  5.  *        modifications by Mark Weiser and Bruce Israel,
  6.  *            University of Maryland
  7.  *
  8.  *              More mods Robert Bond, 12/86
  9.  *        Major mods to run on VMS and AMIGA, 1/17/87
  10.  *
  11.  */
  12.  
  13. #include "sc.h"
  14.  
  15. extern char *malloc();
  16.  
  17. /* default column width */
  18.  
  19. #define DEFWIDTH 10
  20. #define DEFPREC   2
  21.  
  22. #define RESCOL 4  /* columns reserved for row numbers */
  23. #define RESROW 3  /* rows reserved for prompt, error, and column numbers */
  24.  
  25. char curfile[1024];
  26.  
  27. int showme = 1;  /* 1 to display the current cell in the top line */
  28. int batch = 0;
  29.  
  30. error (fmt,a,b,c,d,e) {
  31.     if (batch) fprintf(stderr,fmt,a,b,c,d,e);
  32.     else {
  33.     move (1,0);
  34.     clrtoeol ();
  35.     printw (fmt,a,b,c,d,e);
  36.     }
  37. }
  38.  
  39. int seenerr;
  40.  
  41. yyerror (err)
  42. char *err; {
  43.     if (seenerr) return;
  44.     seenerr++;
  45.     move (1,0);
  46.     clrtoeol ();
  47.     printw ("%s: %.*s <= %s",err,linelim,line,line+linelim);
  48. }
  49.  
  50. struct ent *
  51. lookat(row,col){
  52.     register struct ent **p;
  53.     if (row < 0)
  54.     row = 0;
  55.     else if (row > MAXROWS-1) 
  56.     row = MAXROWS-1;
  57.     if (col < 0) 
  58.     col = 0;
  59.     else if (col > MAXCOLS-1)
  60.     col = MAXCOLS-1;
  61.     p = &tbl[row][col];
  62.     if (*p==0) {
  63.     *p = (struct ent *) malloc (sizeof (struct ent));
  64.     if (row>maxrow) maxrow = row;
  65.     if (col>maxcol) maxcol = col;
  66.     (*p)->label = 0;
  67.     (*p)->flags = 0;
  68.     (*p)->row = row;
  69.     (*p)->col = col;
  70.     (*p)->expr = 0;
  71.     (*p)->v = (double) 0.0;
  72.     } else if ((*p)->flags & is_deleted) 
  73.     debug("But %s%d has been deleted!", coltoa(col), row);
  74.     return *p;
  75. }
  76.  
  77. /*
  78.  * This structure is used to keep ent structs around before they
  79.  * are deleted to allow the sync_refs routine a chance to fix the
  80.  * variable references.
  81.  * We also use it as a last-deleted buffer for the 'p' command.
  82.  */
  83.  
  84. free_ent(p)
  85. register struct ent *p;
  86. {
  87.     p->next = to_fix;
  88.     to_fix = p;
  89.     p->flags |= is_deleted;
  90. }
  91.  
  92. flush_saved()
  93. {
  94.     register struct ent *p;
  95.     register struct ent *q;
  96.  
  97.     if (!(p = to_fix))
  98.     return;
  99.     while (p) {
  100.     clearent(p);
  101.     q = p->next;
  102.     free(p);
  103.     p = q;
  104.     }
  105.     to_fix = 0;
  106. }
  107.  
  108. update () {
  109.     register    row,
  110.                 col;
  111.     register struct ent **p;
  112.     static  lastmx,
  113.             lastmy;
  114.     static  char *under_cursor = " ";
  115.     int     maxcol;
  116.     int     maxrow;
  117.     int     rows;
  118.     int     cols;
  119.     register r;
  120.  
  121.     while (hidden_row[currow])   /* You can't hide the last row or col */
  122.     currow++;
  123.     while (hidden_col[curcol])
  124.     curcol++;
  125.     if (curcol < stcol)
  126.     stcol = curcol, FullUpdate++;
  127.     if (currow < strow)
  128.     strow = currow, FullUpdate++;
  129.     while (1) {
  130.     register    i;
  131.     for (i = stcol, cols = 0, col = RESCOL;
  132.          (col + fwidth[i]) < COLS-1 && i < MAXCOLS; i++) {
  133.         cols++;
  134.         if (hidden_col[i])
  135.         continue;
  136.         col += fwidth[i];
  137.     }
  138.     if (curcol >= stcol + cols)
  139.         stcol++, FullUpdate++;
  140.     else
  141.         break;
  142.     }
  143.     while (1) {
  144.     register    i;
  145.     for (i = strow, rows = 0, row = RESROW;
  146.          row < ROWS && i < MAXROWS; i++) {
  147.         rows++;
  148.         if (hidden_row[i])
  149.         continue;
  150.         row++;
  151.     }
  152.     if (currow >= strow + rows)
  153.         strow++, FullUpdate++;
  154.     else
  155.         break;
  156.     }
  157.     maxcol = stcol + cols - 1;
  158.     maxrow = strow + rows - 1;
  159.     if (FullUpdate) {
  160.     register int i;
  161.     move (2, 0);
  162.     clrtobot ();
  163.     standout();
  164.     for (row=RESROW, i=strow; i <= maxrow; i++) {
  165.         if (hidden_row[i]) 
  166.         continue;
  167.         move(row,0);
  168.         printw("%-*d", RESCOL, i);
  169.         row++;
  170.     }
  171.     move (2,0);
  172.     printw("%*s", RESCOL, " ");
  173.     for (col=RESCOL, i = stcol; i <= maxcol; i++) {
  174.         if (hidden_col[i])
  175.         continue;
  176.         move(2, col);
  177.         printw("%*s", fwidth[i], coltoa(i));
  178.         col += fwidth[i];
  179.     }
  180.     standend();
  181.     }
  182.     for (row = strow, r = RESROW; row <= maxrow; row++) {
  183.     register    c = RESCOL;
  184.     if (hidden_row[row])
  185.         continue;
  186.     for (p = &tbl[row][col = stcol]; col <= maxcol; col++, p++) {
  187.         if (hidden_col[col])
  188.         continue;
  189.         if (*p && ((*p) -> flags & is_changed || FullUpdate)) {
  190.         char   *s;
  191.         move (r, c);
  192.         (*p) -> flags &= ~is_changed;
  193.         if ((*p) -> flags & is_valid)
  194.             printw ("%*.*f", fwidth[col], precision[col], (*p) -> v);
  195.         if (s = (*p) -> label) {
  196.             char field[1024];
  197.  
  198.             strncpy(field,s,fwidth[col]);
  199.             field[fwidth[col]] = 0;
  200.             move (r,(*p) -> flags & is_leftflush
  201.                 ? c : c - strlen (field) + fwidth[col]);
  202.             addstr(field);
  203.         }
  204.         }
  205.         c += fwidth[col];
  206.     }
  207.     r++;
  208.     }
  209.     
  210.     move(lastmy, lastmx);
  211.     if (inch() == '<')
  212.         addstr (under_cursor);
  213.     lastmy =  RESROW;
  214.     for (row = strow; row < currow; row++)
  215.     if (!hidden_row[row])
  216.         lastmy += 1;
  217.     lastmx = RESCOL;
  218.     for (col = stcol; col <= curcol; col++)
  219.     if (!hidden_col[col])
  220.         lastmx += fwidth[col];
  221.     move(lastmy, lastmx);
  222.     *under_cursor = inch();
  223.     addstr ("<");
  224.     move (0, 0);
  225.     clrtoeol ();
  226.     if (linelim >= 0) {
  227.     addstr (">> ");
  228.     addstr (line);
  229.     } else {
  230.     if (showme) {
  231.         register struct ent *p;
  232.         p = tbl[currow][curcol];
  233.         if (p && ((p->flags & is_valid) || p->label)) {
  234.         if (p->expr || !p->label) {
  235.             linelim = 0;
  236.             editexp(currow, curcol);
  237.         } else {
  238.             sprintf(line, "%s", p->label);
  239.         }
  240.         addstr("[");
  241.         addstr (line);
  242.         addstr("]");
  243.         linelim = -1;
  244.         } else {
  245.         addstr("[]");
  246.         }
  247.     }
  248.     move (lastmy, lastmx);
  249.     }
  250.     FullUpdate = 0;
  251. }
  252.  
  253. void
  254. quit()
  255. {
  256.     endwin ();
  257.     exit();
  258. }
  259.  
  260. main (argc, argv)
  261. char  **argv; {
  262.     int     inloop = 1;
  263.     register int   c;
  264.     int     edistate = -1;
  265.     int     arg = 1;
  266.     int     narg;
  267.     int     nedistate = -1;
  268.     int        running = 1;
  269.     {
  270.     register    i;
  271.     for (i = 0; i < MAXCOLS; i++) {
  272.         fwidth[i] = DEFWIDTH;
  273.         precision[i] = DEFPREC;
  274.     }
  275.     }
  276.     linelim = -1;
  277.     curfile[0]=0;
  278.     running = 1;
  279.  
  280.     if (argc > 1 && (! strcmp(argv[1],"-b"))) {
  281.     argc--, argv++;
  282.     batch = 1;
  283.     }
  284.  
  285.     if (! batch) {
  286.     initscr ();
  287.     }
  288.     initkbd();
  289.     if (argc > 1) {
  290.     strcpy(curfile,argv[1]);
  291.     readfile (argv[1],0);
  292.     }
  293.     modflg = 0;
  294.     if (batch) exit(0);
  295.     error ("VC 2.1  Type '?' for help.");
  296.     FullUpdate++;
  297.     while (inloop) { running = 1;
  298.     while (running) {
  299.     nedistate = -1;
  300.     narg = 1;
  301.     if (edistate < 0 && linelim < 0 && (changed || FullUpdate))
  302.         EvalAll (), changed = 0;
  303.     update ();
  304.     refresh ();
  305.     move (1, 0);
  306.     clrtoeol ();
  307.     fflush (stdout);
  308.     seenerr = 0;
  309.     if (((c = nmgetch ()) < ' ') || ( c == 0177 ))
  310.         switch (c) {
  311.         case ctl (z):
  312.             quit();
  313.             break;
  314.         case ctl (r):
  315.             FullUpdate++;
  316.             touchwin();
  317.             clear();
  318.             break;
  319.         default:
  320.             error ("No such command  (^%c)", c + 0100);
  321.             break;
  322.         case ctl (b):
  323.             while (--arg>=0) {
  324.             if (curcol)
  325.                 curcol--;
  326.             else
  327.                 error ("At column A");
  328.             while(hidden_col[curcol] && curcol)
  329.                 curcol--;
  330.             }
  331.             break;
  332.         case ctl (c):
  333.             running = 0;
  334.             break;
  335.         case ctl (f):
  336.             while (--arg>=0) {
  337.             if (curcol < MAXCOLS - 1)
  338.                 curcol++;
  339.             else
  340.                 error ("The table can't be any wider");
  341.             while(hidden_col[curcol]&&(curcol<MAXCOLS-1))
  342.                 curcol++;
  343.             }
  344.             break;
  345.         case ctl (g):
  346.         case ctl ([):
  347.             linelim = -1;
  348.             move (1, 0);
  349.             clrtoeol ();
  350.             break;
  351.         case 0177:
  352.         case ctl (h):
  353.             while (--arg>=0) if (linelim > 0)
  354.             line[--linelim] = 0;
  355.             break;
  356.         case ctl (l):
  357.             FullUpdate++;
  358.             break;
  359.         case ctl (m):
  360.             if (linelim < 0)
  361.             line[linelim = 0] = 0;
  362.             else {
  363.             linelim = 0;
  364.             yyparse ();
  365.             linelim = -1;
  366.             }
  367.             break;
  368.         case ctl (n):
  369.             while (--arg>=0) {
  370.             if (currow < MAXROWS - 1)
  371.                 currow++;
  372.             else
  373.                 error ("The table can't be any longer");
  374.             while (hidden_row[currow] && (currow < MAXROWS - 1))
  375.                 currow++;
  376.             }
  377.             break;
  378.         case ctl (p):
  379.             while (--arg>=0) {
  380.             if (currow)
  381.                 currow--;
  382.             else
  383.                 error ("At row zero");
  384.             while (hidden_row[currow] && currow)
  385.                 currow--;
  386.             }
  387.             break;
  388.         case ctl (q):
  389.             break;    /* ignore flow control */
  390.         case ctl (s):
  391.             break;    /* ignore flow control */
  392.         case ctl (t):
  393.             showme ^= 1;
  394.             break;
  395.         case ctl (u):
  396.             narg = arg * 4;
  397.             nedistate = 1;
  398.             break;
  399.         case ctl (v):    /* insert variable name */
  400.             if (linelim > 0) {
  401.             sprintf (line+linelim,"%s%d", coltoa(curcol), currow);
  402.             linelim = strlen (line);
  403.             }
  404.             break;
  405.         case ctl (e):    /* insert variable expression */
  406.             if (linelim > 0) editexp(currow,curcol);
  407.             break;
  408.         case ctl (a):    /* insert variable value */
  409.             if (linelim > 0) {
  410.             struct ent *p = tbl[currow][curcol];
  411.  
  412.             if (p && p -> flags & is_valid) {
  413.                 sprintf (line + linelim, "%.*f",
  414.                     precision[curcol],p -> v);
  415.                 linelim = strlen (line);
  416.             }
  417.             }
  418.             break;
  419.         }
  420.     else
  421.         if ('0' <= c && c <= '9' && (linelim < 0 || edistate >= 0)) {
  422.         if (edistate != 0) {
  423.             if (c == '0')      /* just a '0' goes to left col */
  424.             curcol = 0;
  425.             else {
  426.                 nedistate = 0;
  427.                 narg = c - '0';
  428.             }
  429.         } else {
  430.             nedistate = 0;
  431.             narg = arg * 10 + (c - '0');
  432.         }
  433.         }
  434.         else
  435.         if (linelim >= 0) {
  436.             line[linelim++] = c;
  437.             line[linelim] = 0;
  438.         }
  439.         else
  440.             switch (c) {
  441.             case '.':
  442.                 nedistate = 1;
  443.                 break;
  444.             case ':':
  445.                 break;    /* Be nice to vi users */
  446.             case '=':
  447.                 sprintf(line,"let %s%d = ",coltoa(curcol),currow);
  448.                 linelim = strlen (line);
  449.                 break;
  450.             case '/':
  451.                 sprintf(line,"copy [to] %s%d [from] ", 
  452.                       coltoa(curcol), currow);
  453.                 linelim = strlen (line);
  454.                 break;
  455.             case '$':
  456.                 curcol = MAXCOLS - 1;
  457.                 while (!tbl[currow][curcol] && curcol > 0)
  458.                 curcol--;
  459.                 break;
  460.             case '?':
  461.                 help ();
  462.                 break;
  463.             case '"':
  464.                 sprintf (line, "label %s%d = \"",
  465.                         coltoa(curcol), currow);
  466.                 linelim = strlen (line);
  467.                 break;
  468.             case '<':
  469.                 sprintf (line, "leftstring %s%d = \"",
  470.                     coltoa(curcol), currow);
  471.                 linelim = strlen (line);
  472.                 break;
  473.             case '>':
  474.                 sprintf (line, "rightstring %s%d = \"",
  475.                     coltoa(curcol), currow);
  476.                 linelim = strlen (line);
  477.                 break;
  478.             case 'e':
  479.                 editv (currow, curcol);
  480.                 break;
  481.             case 'E':
  482.                 edits (currow, curcol);
  483.                 break;
  484.             case 'f':
  485.                 sprintf (line, "format [for column] %s [is] ",
  486.                     coltoa(curcol));
  487.                 error("Current format is %d %d",
  488.                     fwidth[curcol],precision[curcol]);
  489.                 linelim = strlen (line);
  490.                 break;
  491.             case 'P':
  492.                 sprintf (line, "put [database into] \"");
  493.                 if (*curfile)
  494.                 error("default file is '%s'",curfile);
  495.                 linelim = strlen (line);
  496.                 break;
  497.             case 'M':
  498.                 sprintf (line, "merge [database from] \"");
  499.                 linelim = strlen (line);
  500.                 break;
  501.             case 'G':
  502.                 sprintf (line, "get [database from] \"");
  503.                 if (*curfile)
  504.                 error("default file is '%s'",curfile);
  505.                 linelim = strlen (line);
  506.                 break;
  507.             case 'W':
  508.                 sprintf (line, "write [listing to] \"");
  509.                 linelim = strlen (line);
  510.                 break;
  511.             case 'T':    /* tbl output */
  512.                 sprintf (line, "tbl [listing to] \"");
  513.                 linelim = strlen (line);
  514.                 break;
  515.             case 'i':
  516.                 switch (get_qual()) {
  517.                 case 'r':
  518.                 insertrow(arg);
  519.                 break;
  520.                 case 'c':
  521.                 insertcol(arg);
  522.                 break;
  523.                 default:
  524.                 break;
  525.                 }
  526.                 break;
  527.             case 'd':
  528.                 switch (get_qual()) {
  529.                 case 'r':
  530.                 deleterow(arg);
  531.                 break;
  532.                 case 'c':
  533.                 deletecol(arg);
  534.                 break;
  535.                 default:
  536.                 break;
  537.                 }
  538.                 break;
  539.             case 'v':
  540.                 switch (get_qual()) {
  541.                 case 'r':
  542.                 valueizerow(arg);
  543.                 break;
  544.                 case 'c':
  545.                 valueizecol(arg);
  546.                 break;
  547.                 default:
  548.                 break;
  549.                 }
  550.                 break;
  551.             case 'p':
  552.                 {
  553.                 register qual;
  554.                 qual = get_qual();
  555.                 while (arg--)
  556.                     pullcells(qual);
  557.                 break;
  558.                 }
  559.             case 'x':
  560.                 {
  561.                 register struct ent **p;
  562.                 register int c;
  563.                 flush_saved();
  564.                 for (c = curcol; arg-- && c < MAXCOLS; c++) {
  565.                 p = &tbl[currow][c];
  566.                 if (*p) {
  567.                         free_ent(*p);
  568.                         *p = 0;
  569.                 }
  570.                 }
  571.                 sync_refs();
  572.                 FullUpdate++;
  573.                 }
  574.                 break;
  575.             case 'Q':
  576.             case 'q':
  577.                 running = 0;
  578.                 break;
  579.             case 'h':
  580.                 while (--arg>=0) {
  581.                 if (curcol)
  582.                     curcol--;
  583.                 else
  584.                     error ("At column A");
  585.                 while(hidden_col[curcol] && curcol)
  586.                     curcol--;
  587.                 }
  588.                 break;
  589.             case 'j':
  590.                 while (--arg>=0) {
  591.                 if (currow < MAXROWS - 1)
  592.                     currow++;
  593.                 else
  594.                     error ("The table can't be any longer");
  595.                 while (hidden_row[currow]&&(currow<MAXROWS-1))
  596.                     currow++;
  597.                 }
  598.                 break;
  599.             case 'k':
  600.                 while (--arg>=0) {
  601.                 if (currow)
  602.                     currow--;
  603.                 else
  604.                     error ("At row zero");
  605.                 while (hidden_row[currow] && currow)
  606.                     currow--;
  607.                 }
  608.                 break;
  609.             case 'l':
  610.                 while (--arg>=0) {
  611.                 if (curcol < MAXCOLS - 1)
  612.                     curcol++;
  613.                 else
  614.                     error ("The table can't be any wider");
  615.                 while(hidden_col[curcol]&&(curcol<MAXCOLS-1))
  616.                     curcol++;
  617.                 }
  618.                 break;
  619.             case 'm':
  620.                 savedrow = currow;
  621.                 savedcol = curcol;
  622.                 break;
  623.             case 'c': {
  624.                 register struct ent *p = tbl[savedrow][savedcol];
  625.                 register c;
  626.                 register struct ent *n;
  627.                 if (!p)
  628.                 break;
  629.                 FullUpdate++;
  630.                 modflg++;
  631.                 for (c = curcol; arg-- && c < MAXCOLS; c++) {
  632.                 n = lookat (currow, c);
  633.                 clearent(n);
  634.                 n -> flags = p -> flags;
  635.                 n -> v = p -> v;
  636.                 n -> expr = copye(p->expr,
  637.                         currow - savedrow,
  638.                         c - savedcol);
  639.                 n -> label = 0;
  640.                 if (p -> label) {
  641.                     n -> label = (char *)
  642.                          malloc(strlen(p->label)+1);
  643.                 strcpy (n -> label, p -> label);
  644.                 }
  645.                 }
  646.                 break;
  647.             }
  648.             case 'z':
  649.                 switch (get_qual()) {
  650.                 case 'r':
  651.                 hiderow(arg);
  652.                 break;
  653.                 case 'c':
  654.                 hidecol(arg);
  655.                 break;
  656.                 default:
  657.                 break;
  658.                 }
  659.                 break;
  660.             case 's':
  661.                 switch (get_qual()) {
  662.                 case 'r':
  663.                 showrow_op();
  664.                 break;
  665.                 case 'c':
  666.                 showcol_op();
  667.                 break;
  668.                 default:
  669.                 break;
  670.                 }
  671.                 break;
  672.             case 'a':
  673.                 switch (get_qual()) {
  674.                 case 'r':
  675.                 while (arg--)
  676.                     duprow();
  677.                 break;
  678.                 case 'c':
  679.                 while (arg--)
  680.                     dupcol();
  681.                 break;
  682.                 default:
  683.                 break;
  684.                 }
  685.                 break;
  686.             default:
  687.                 if ((c & 0177) != c)
  688.                 error("Weird character, decimal '%d'.\n",
  689.                     (int) c);
  690.                 else error ("No such command  (%c)", c);
  691.                 break;
  692.             }
  693.     edistate = nedistate;
  694.     arg = narg;
  695.     }                /* while (running) */
  696.     inloop = modcheck(" before exiting");
  697.     }                /*  while (inloop) */
  698.     endwin ();
  699. }
  700.  
  701. modcheck(endstr) char *endstr; {
  702.     if (modflg && curfile[0]) {
  703.     char ch, lin[100];
  704.  
  705.     move (0, 0);
  706.     clrtoeol ();
  707.     sprintf (lin,"File '%s' is modified, save%s? ",curfile,endstr);
  708.     addstr (lin);
  709.     refresh();
  710.     ch = nmgetch();
  711.     if (ch == 'y' || ch == 'Y') writefile(curfile);
  712.     else if (ch == ctl (g)) return(1);
  713.     }
  714.     return(0);
  715. }
  716.     
  717. writefile (fname)
  718. char *fname; {
  719.     register FILE *f;
  720.     register struct ent **p;
  721.     register r, c;
  722.     char save[1024];
  723.  
  724.     if (*fname == 0) fname = &curfile[0];
  725.  
  726.     strcpy(save,fname);
  727.  
  728.     f = fopen (fname, "w");
  729.     if (f==0) {
  730.     error ("Can't create %s", fname);
  731.     return;
  732.     }
  733.  
  734.     fprintf (f, "# This data file was generated by the Spreadsheet ");
  735.     fprintf (f, "Calculator.\n");
  736.     fprintf (f, "# You almost certainly shouldn't edit it.\n\n");
  737.     for (c=0; c<MAXCOLS; c++)
  738.     if (fwidth[c] != DEFWIDTH || precision[c] != DEFPREC)
  739.         fprintf (f, "format %s %d %d\n",coltoa(c),fwidth[c],precision[c]);
  740.     for (r=0; r<=maxrow; r++) {
  741.     p = &tbl[r][0];
  742.     for (c=0; c<=maxcol; c++, p++)
  743.         if (*p) {
  744.         if ((*p)->label)
  745.             fprintf (f, "%sstring %s%d = \"%s\"\n",
  746.                 (*p)->flags&is_leftflush ? "left" : "right",
  747.                 coltoa(c),r,(*p)->label);
  748.         if ((*p)->flags&is_valid) {
  749.             editv (r, c);
  750.             fprintf (f, "%s\n",line);
  751.         }
  752.         }
  753.     }
  754.     fclose (f);
  755.     strcpy(curfile,save);
  756.  
  757.     modflg = 0;
  758.     error("File '%s' written.",curfile);
  759. }
  760.  
  761. readfile (fname,eraseflg)
  762. char *fname; int eraseflg; {
  763.     register FILE *f;
  764.     char save[1024];
  765.  
  766.     if (*fname == 0) fname = &curfile[0];
  767.     strcpy(save,fname);
  768.  
  769.     if (eraseflg && strcmp(fname,curfile) && modcheck(" first")) return;
  770.  
  771.     f = fopen (save, "r");
  772.     if (f==0) {
  773.     error ("Can't read %s", save);
  774.     return;
  775.     }
  776.  
  777.     if (eraseflg) erasedb ();
  778.  
  779.     while (fgets(line,sizeof line,f)) {
  780.     linelim = 0;
  781.     if (line[0] != '#') yyparse ();
  782.     }
  783.     fclose (f);
  784.     linelim = -1;
  785.     modflg++;
  786.     if (eraseflg) {
  787.     strcpy(curfile,save);
  788.     modflg = 0;
  789.     }
  790.     EvalAll();
  791. }
  792.  
  793. erasedb () {
  794.     register r, c;
  795.     for (c = 0; c<=maxcol; c++) {
  796.     fwidth[c] = DEFWIDTH;
  797.     precision[c] = DEFPREC;
  798.     }
  799.  
  800.     for (r = 0; r<=maxrow; r++) {
  801.     register struct ent **p = &tbl[r][0];
  802.     for (c=0; c++<=maxcol; p++)
  803.         if (*p) {
  804.         if ((*p)->expr) efree ((*p) -> expr);
  805.         if ((*p)->label) free ((*p) -> label);
  806.         free (*p);
  807.         *p = 0;
  808.         }
  809.     }
  810.     maxrow = 0;
  811.     maxcol = 0;
  812.     FullUpdate++;
  813. }
  814.  
  815.